#!/bin/bash

# Get the users actual home directory in case we're running this with sudo
user_home=$(eval echo ~${SUDO_USER})

touch $user_home/.genentriesrc
source $user_home/.genentriesrc

if [ -z "$svgpath" ]; then
  svgpath="svgicons"
fi
if [ -z "$iconsize" ]; then
  iconsize=$XLUNCHICONSIZE
fi
if [ -z "$iconsize" ]; then
  iconsize=48
fi

while [[ $# -gt 0 ]]
do
key="$1"

case $key in
    -s|--size)
    iconsize="$2"
    shift # past argument
    ;;
    -p|--path)
    svgpath="$2"
    shift # past argument
    ;;
    -f|--file)
    desktopfile="$2"
    shift # past argument
    ;;
    -t|--theme)
    icontheme="$2"
    shift
    ;;
    -c|--category)
    forcecategory="$2"
    shift
    ;;
    -d|--debug)
    debug="true"
    ;;
    -h|--help)
    echo "Usage: genentries [-s|--size <icon size>] [-p|--path <path for converted icons>] [-f|--file <desktop file to parse>] [-t|--theme <manually theme override>] [-d|--debug] [-c|--category <name of category to generate>]"
    exit 0
    ;;
    *)
    echo "Unknown option $key"
    exit 1
    ;;
esac
shift # past argument or value
done

globalappfolder=/usr/share/applications
localappfolder=$user_home/.local/share/applications
snapappfolder=/var/lib/snapd/desktop/applications
pixmaps=/usr/share/pixmaps

if [ -z "$icontheme" ]; then
  icontheme=$(cat $user_home/.gtkrc-2.0 2>/dev/null| sed -n 's/^gtk-icon-theme-name="\([^"]*\)"$/\1/p')
  if [ -z "$icontheme" ]; then
    icontheme=$(cat $user_home/.config/gtk-3.0/settings.ini 2>/dev/null| sed -n 's/^gtk-icon-theme-name="\([^"]*\)"$/\1/p')
  fi
  if [ -z "$icontheme" ]; then
    icontheme=$(cat $user_home/.kde4/share/config/kdeglobals 2>/dev/null| grep -A 1 "\[Icons\]" | tail -n1 | sed -n 's/^Theme=//p')
  fi
  if [ -z "$icontheme" ] && [ $(type xfconf-query >/dev/null 2>&1) ]; then
    icontheme=$(xfconf-query -c xsettings -p /Net/ThemeName)
  fi
  if [ -z "$icontheme" ] && [ $(type gsettings >/dev/null 2>&1) ]; then
    icontheme=$(gsettings get org.gnome.desktop.interface gtk-theme)
  fi
fi
cansvg=$(type convert >/dev/null 2>&1 && echo "true" || echo "false")
# File formats supported by most imlib2 installations.
declare -a formats
formats=("png" "jpg" "jpeg" "tif" "tiff" "xpm" "bmp" "gif" "pnm" "tga")
if $cansvg; then
  formats+=("svg")
fi

# Debug statements
if [ "$debug" == "true" ]; then
  echo $(bash --version | head -n1) >&2
  echo $user_home >&2
  echo $icontheme  >&2
  echo $cansvg >&2
  for t in "${formats[@]}"; do
    echo -n "$t " >&2
  done
  echo "" >&2
  echo $svgpath >&2
  echo $iconsize >&2
fi

echo "Generating entries file..." >&2
if [ -z "$icontheme" ]; then
  echo "Unable to auto-detect icon theme, defaulting to 'hicolor'. Use --theme '<theme name>' to manually override theme." >&2
  icontheme="hicolor"
  inherits="hicolor"
else
  if [ -z "$indexfile" ]; then
    indexfile=$(find -L "$user_home/.local/share/icons/$icontheme" -name "index.theme" -print -quit 2>/dev/null)
  fi
  if [ -z "$indexfile" ]; then
    indexfile=$(find -L "$user_home/.icons/$icontheme" -name "index.theme" -print quit 2>/dev/null)
  fi
  if [ -z "$indexfile" ]; then
    indexfile=$(find -L "/usr/share/icons/$icontheme" -name "index.theme" -print -quit 2>/dev/null)
  fi
  if [ -z "$indexfile" ]; then
    echo "Could not find index.theme for theme $icontheme"
    exit 1
  fi
  inherits=$(cat "$indexfile" | sed -n "s|^Inherits=\(.*\)$|\1|p" | sed "s|,|\n|g" | grep -v "^hicolor$")
  inherits=$(echo -e "$icontheme\n$inherits\nhicolor" | sed "/^$/d")
fi
if [ "$debug" == "true" ]; then
  echo $indexfile >&2
  echo $inherits >&2
fi

function elementIn {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}

function readdesktopfile {
  fdata=$(cat "$1")
  if ! [[ -z $(echo "$fdata" | grep -i "^NoDisplay=true$") ]]; then
    # Add a placeholder so the global app folder won't override it
    echo ";;"
  else
    name="$(echo "$fdata" | grep -i "^Name=" | head -n 1 | cut -d "=" -f 2-)"
    # Remove % arguments from the .desktop files as they are not supported by xlunch (WARNING: this might cause programs to misbehave)
    cmd="$(echo "$fdata" | grep -i "^Exec=" | head -n 1 | cut -d "=" -f 2- | sed 's/ %[UuFfDdNnickvm]//g')"
    iconname="$(echo "$fdata" | grep -i "^Icon=" | head -n 1 | cut -d "=" -f 2-)"
    useterm="$(echo "$fdata" | grep -i "^Terminal=" | head -n 1 | cut -d "=" -f 2-)"
    categories="$(echo "$fdata" | grep -i "^Categories=" | head -n 1 | cut -d "=" -f 2-)"
    if ! [[ "$categories" = *"$forcecategory"* ]]; then
      return
    fi
    if [ "$useterm" = "true" ]; then
      cmd="$TERM -e ""$cmd"
    fi

    if [ "$iconname" != "" ]; then
      # Look for icons in the correct size
      #>&2 echo "$1"
      #>&2  echo "$iconname"
      if [ -f "$iconname" ] && elementIn "${iconname##*.}" "${formats[@]}"; then
        icon="$iconname"
        iconname=$(basename "$iconname")
        iconname="${iconname%.*}"
      else
        if elementIn "${iconname##*.}" "${formats[@]}"; then
          iconname=${iconname%.*}
        fi
        # Create arguments for the find call to get all supported file formats
        declare -a findargs
        findargs=()
        for t in "${formats[@]}"; do
          findargs+=(-name "$iconname.$t" -o)
        done
        icon=""
        for theme in $inherits; do
          paths=()
          if [ -d "$user_home/.local/share/icons/$theme" ]; then
            paths+=("$user_home/.local/share/icons/$theme")
          fi
          if [ -d "$user_home/.icons/$theme" ]; then
            paths+=("$user_home/.icons/$theme")
          fi
          if [ -d "/usr/share/icons/$theme" ]; then
            paths+=("/usr/share/icons/$theme")
          fi
          for themepath in ${paths[@]}; do
            if [ ! -d "$themepath" ] && [ ! -L "$themepath" ]; then
              continue
            fi
            sizes=$(find -L "$themepath/" -type d | sed -n "s|^"$themepath"/\([^/]*/\)\{0,1\}\([0-9]*\)[^/]*$|\2|p" | sort -u | awk -v iconsize="$iconsize" '{if($0 > iconsize) print "g "$0}{if($0 == iconsize) print "e "$0}{if ($0 < iconsize) print "l "$0}')
            sizes=$(echo -e "$(echo "$sizes" | grep "^e.*")\n$(echo "$sizes" | grep "^g.*" | sort -k 2.1n)\nscalable\n$(echo "$sizes" | grep "^l.*" | sort -k 2.1nr)")
            sizes=$(echo "$sizes" | sed "s|^. ||")
            for size in $sizes; do
              while read path; do
                if ! [ -z "$path" ]; then
                  icon=$(find -L "$path" -type f \( "${findargs[@]}" -false \) -print -quit )
                  if ! [ -z "$icon" ]; then
                    break 4
                  fi
                fi
              done <<< $(find -L "$themepath/" -type d | grep "^$themepath/\([^/]*/\)\?$size\(x$size\)\?$")
            done
          done
        done

        # If we can't find anything that matches the theme, just search anywhere
        if [ -z "$icon" ]; then
          icon="$(find -L "$pixmaps" -type f \( "${findargs[@]}" -false \) -print -quit)"
        fi
        if [ -z "$icon" ] && [ -d "$user_home/.local/share/icons" ]; then
          icon=$(find -L "$user_home/.local/share/icons" -type f \( "${findargs[@]}" -false \) -print -quit)
        fi
        if [ -z "$icon" ] && [ -d "$user_home/.icons" ]; then
          icon=$(find -L "$user_home/.icons" -type f \( "${findargs[@]}" -false \) -print -quit)
        fi
        if [ -z "$icon" ] && [ -d "/usr/share/icons" ]; then
          icon=$(find -L "/usr/share/icons" -type f \( "${findargs[@]}" -false \) -print -quit)
        fi
      fi

      if [ "${icon: -4}" == ".svg" ]; then
        if ! [ -f "$svgpath/"$iconname".png" ]; then
          >&2 echo "Converting $icon to png"
          mkdir -p "$svgpath"
          convert -density 500 -resize "$iconsize"x"$iconsize" -background none "$icon" "$svgpath/"$iconname".png"
        fi
        icon="$svgpath/"$iconname".png"
      fi

      # If we have all the data we need, output an entry. Empty icon is fine
      if [ "$cmd" != "" -a "$name" != "" ]; then
        echo "$name;$icon;$cmd"
      else
        >&2 echo "Couldn't find all required data for $1"
      fi
    fi
  fi
}

if [ ! -z "$desktopfile" ]; then
readdesktopfile "$desktopfile"
else
if ! [ -z "$icontheme" ]; then
  # Create an assoc array (ie. hashmap, ie. table, ie. you get the point)
  declare -A applications

  # Set for in separator to newline
  IFS=$'\n'

  # Iterate over desktop files and add them to the array if they don't already exist
  files=$(find -L "$localappfolder" "$globalappfolder" "$snapappfolder" -name "*.desktop" 2>/dev/null)
  for desktopfile in $files
  do
    bname=$(basename "$desktopfile")
    if ! [[ ${applications[$bname]} ]]; then
      entry=$(readdesktopfile "$desktopfile")
      if ! [ -z "$entry" ]; then
        applications["$bname"]="$entry"
      fi
    fi
  done

  # Get all the entries and write them out sorted and unique while removing the placeholder
    for key in "${!applications[@]}"; do
      echo "${applications[$key]}"
    done | sort | uniq | grep -v "^;;$"
  fi
fi
